﻿using System;
using UnityEditor;
using UnityEngine;

namespace UPA
{
    [CustomEditor(typeof(ProcessActionGroup))]
    public partial class ProcessActionGroupDrawer:Editor
    {
        private const string SelectSettingIndexKey = "ProcessActionGroupDrawer:SelectSettingIndexKey";
        private enum State
        {
            Main,
            Template,
            Setting
        }

        private State _state = State.Main;
        private Vector2 _scrollValue;
        private ProcessActionGroup _group;
        private string[] _settingNames;
        
        private GUIStyle _btnStyle;
        private GUIStyle _popupStyle;
        private GUIStyle _textFieldStyle;
        private GUIContent _tmpContent;
        
        public override void OnInspectorGUI()
        {
            if (_btnStyle == null)
            {
                _btnStyle = new GUIStyle(GUI.skin.button) {fontSize = 16,stretchWidth = false};
                _popupStyle = new GUIStyle("popup") {fontSize = 16,fixedHeight = _btnStyle.CalcSize(new GUIContent("测试")).y};
                _textFieldStyle = new GUIStyle(GUI.skin.textField) {fontSize = 16};
                _tmpContent = new GUIContent();
            }
            
            serializedObject.Update();
            DrawMenu();
            switch (_state)
            {
                case State.Main:
                    DrawMain();
                    break;
                case State.Template:
                    DrawTemplate();
                    break;
                case State.Setting:
                    DrawSetting();
                    break;
            }
            serializedObject.ApplyModifiedProperties();
        }
        
        private void OnEnable()
        {
            _group = target as ProcessActionGroup;
            if (!_group)
            {
                return;
            }
            
            _group.InitDefaultSetting();

            var guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(_group));
            _group.CurSelectSettingIndex = EditorPrefs.GetInt(SelectSettingIndexKey+$"_{guid}",0);
            RefreshMain();
        }

        private void DrawMenu()
        {
            EditorGUILayout.BeginHorizontal();
            if (_state == State.Main)
            {
                if (GUILayout.Button("模板管理",_btnStyle))
                {
                    _state = State.Template;
                    RefreshTemplate();
                }

                if (_group.ActionUnits.Count > 0)
                {
                    if (GUILayout.Button("配置管理", _btnStyle))
                    {
                        _state = State.Setting;
                        RefreshSetting();
                    }

                    if (GUILayout.Button("保存配置", _btnStyle))
                    {
                        AssetDatabase.SaveAssetIfDirty(serializedObject.targetObject);
                    }

                    var settingIndex = EditorGUILayout.Popup(_group.CurSelectSettingIndex, _settingNames,_popupStyle);
                    if (settingIndex != _group.CurSelectSettingIndex)
                    {
                        _group.CurSelectSettingIndex = settingIndex;
                        var guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(_group));
                        EditorPrefs.SetInt(SelectSettingIndexKey+$"_{guid}", _group.CurSelectSettingIndex);
                        RefreshMain();
                    }
                }
            }
            else
            {
                if (GUILayout.Button("返回", _btnStyle))
                {
                    _state = State.Main;
                    RefreshMain();
                }
            }
            
            EditorGUILayout.EndHorizontal();
        }

        private void DrawMain()
        {
            if (_group.ActionUnits.Count == 0)
            {
                return;
            }
            _scrollValue = GUILayout.BeginScrollView(_scrollValue);
            DrawAction();
            GUILayout.EndScrollView();
            DrawExecute();
        }

        private void DrawExecute()
        {
            if (_group.ActionUnits.Count == 0)
            {
                return;
            }
            if (GUILayout.Button("全部执行",_btnStyle,GUILayout.ExpandWidth(true),GUILayout.Height(50)))
            {
                Execute(0);
            }
        }

        private void DrawAction()
        {
            for (int i = 0; i < _group.ActionUnits.Count; i++)
            {
                var unit = _group.ActionUnits[i];
                
                var originColor = GUI.color;
                GUILayout.BeginHorizontal();
                if (unit.Disabled)
                {
                    if(GUILayout.Button("启用",_btnStyle))
                    {
                        unit.Disabled = false;
                    }
                }
                else
                {
                    if(GUILayout.Button("禁用",_btnStyle))
                    {
                        unit.Disabled = true;
                    }
                }

                if (unit.Action == null)
                {
                    GUI.color = Color.red;
                }
                else if (unit.Disabled)
                {
                    GUI.color = Color.gray;
                }
                GUILayout.Label(unit.Name,_textFieldStyle);
                GUI.color = originColor;
                
                if (GUILayout.Button("执行", _btnStyle))
                {
                    Execute(i,1);
                }

                if (GUILayout.Button("向下执行", _btnStyle))
                {
                    Execute(i);
                }
               
                GUILayout.EndHorizontal();

                if (unit.Disabled || unit.Action?.RequiredArgument == null)
                {
                    continue;
                }
                
                var property = serializedObject.FindProperty("settings")?
                    .GetArrayElementAtIndex(_group.CurSelectSettingIndex).FindPropertyRelative("arguments")?
                    .GetArrayElementAtIndex(i);
                if (property != null)
                {
                    EditorGUILayout.PropertyField(property,new GUIContent("参数"),true);
                }
            }
        }
        
        private void RefreshMain()
        {
            RefreshSettingNames();
        }

        private void RefreshSettingNames()
        {
            _settingNames = new string[_group.Settings.Count];
            for (int i = 0; i < _group.Settings.Count; i++)
            {
                _settingNames[i] = _group.Settings[i].Name;
            }
        }

        private void Execute(int startIndex,int length = -1)
        {
            if (startIndex < 0)
            {
                startIndex = 0;
            }
            
            int executeCount = length;
            if (length < 0)
            {
                executeCount = _group.ActionUnits.Count - startIndex;
            }
            
            string errMsg = string.Empty;
            bool finished = true;
            for (int i = startIndex; executeCount > 0 && i < _group.ActionUnits.Count; i++)
            {
                var action = _group.ActionUnits[i].Action;
                if (_group.ActionUnits[i].Disabled || action == null)
                {
                    continue;
                }
               
                try
                {
                    var result = action.Execute();
                    if (!result.Finished)
                    {
                        errMsg = $"{action.Name}:{result.ErrorMessage}";
                        finished = false;
                        break;
                    }

                    executeCount--;
                }
                catch (Exception e)
                {
                    Debug.LogError(e);
                    errMsg = $"{action.Name}抛出异常,详细信息请查看日志";
                    finished = false;
                    break;
                }
            }

            if (!finished)
            {
                EditorUtility.DisplayDialog("执行失败", errMsg, "确定");
            }
            else
            {
                EditorUtility.DisplayDialog("执行成功", "所有流程正确执行完毕", "确定");
            }
        }
    }
}